package cn.basic.auth.service.impl;

import cn.basic.auth.annotation.BasicPermission;
import cn.basic.auth.domain.Permission;
import cn.basic.auth.mapper.PermissionMapper;
import cn.basic.auth.vo.query.PermissionQuery;
import cn.basic.auth.service.IPermissionScanService;
import cn.basic.auth.vo.result.PermissionVo;
import cn.basic.common.service.impl.IBaseServiceImpl;
import cn.basic.utils.ClassUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * @description:
 * 权限--service实现类impl
 * @date: 2023/3/3 16:09
 * @author: ZhaoLc
 * @version: 1.0
 */
@Service
@Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
@SuppressWarnings({"all"})
public class IPermissionScanServiceImpl extends IBaseServiceImpl<Permission,PermissionQuery,PermissionVo> implements IPermissionScanService {


    @Value("${permission.basic-scan-package}")
    private String basicScanPackage;

    @Autowired
    PermissionMapper permissionMapper;

    @Override
    public void scan() {
        System.out.println(basicScanPackage);

        List<Class> clazzs = ClassUtils.getAllClassName(this.basicScanPackage);
        List<Permission> permissions = new ArrayList<>();

        if(clazzs.size()>0) {
            // 判断类上是否有注解
            // 判断方法上是否有注解
            for (Class clazz:clazzs) {
                BasicPermission clazzAnnotation =(BasicPermission)clazz.getAnnotation(BasicPermission.class);
                System.out.println(clazzAnnotation);
                if (Objects.isNull(clazzAnnotation)) {
                    continue;
                }
                // 获取请求地址 类url
                RequestMapping clazzMapping = (RequestMapping) clazz.getAnnotation(RequestMapping.class);
                String clazzUrl = clazzMapping.value()[0];
                System.out.println(clazzMapping);

                // 封装
                Permission parent = new Permission();
                parent.setName(clazzAnnotation.name());
                parent.setDesc(clazzAnnotation.desc());
                parent.setUrl(clazzUrl);
                parent.setSn(clazz.getSimpleName());
                permissions.add(parent);

                Method[] methods = clazz.getMethods();
                for (Method method : methods) {
                    BasicPermission basicPermission = method.getAnnotation(BasicPermission.class);
                    if (Objects.isNull(basicPermission)) {
                        continue;
                    }
                    // 处理sn
                    Permission permission = new Permission();
                    permission.setName(basicPermission.name());
                    permission.setDesc(basicPermission.desc());
                    // 处理sn  类名:方法名
                    String sn = clazz.getSimpleName()+":"+method.getName();
                    permission.setSn(sn);
                    // 处理url  url指的是前端在访问时需要访问的url,所以它是类上面的@RequestMapping的值+方法上面的那个url
                    String methodUrl = getMethodUrl(method);
                    permission.setUrl(clazzUrl+methodUrl);
                    // 以类上面解析的permission对象作为父权限对象
                    permission.setParent(parent);
                    permissions.add(permission);
                }
            }
        }
        permissionMapper.removeAll();
        for (Permission permission : permissions) {
            permissionMapper.insert(permission);
        }
    }

    @Override
    public List<Long> getAuthByRole(Long id) {
        return permissionMapper.loadTreeById(id);
    }

    /**
     * 获取方法上面的url
     * @param method 方法反射
     * @return String
     */
    private String getMethodUrl(Method method) {
        String methodUrl = "";
        PutMapping putMapping = method.getAnnotation(PutMapping.class);
        if(Objects.nonNull(putMapping)){
            methodUrl = putMapping.value().length > 0 ? putMapping.value()[0] : "";
        }
        PostMapping postMapping = method.getAnnotation(PostMapping.class);
        if(Objects.nonNull(postMapping)){
            methodUrl = postMapping.value().length > 0 ? postMapping.value()[0] : "";
        }
        GetMapping getMapping = method.getAnnotation(GetMapping.class);
        if(Objects.nonNull(getMapping)){
            methodUrl = getMapping.value().length > 0 ? getMapping.value()[0] : "";
        }
        DeleteMapping deleteMapping = method.getAnnotation(DeleteMapping.class);
        if(Objects.nonNull(deleteMapping)){
            methodUrl = deleteMapping.value().length > 0 ? deleteMapping.value()[0] : "";
        }
        PatchMapping patchMapping = method.getAnnotation(PatchMapping.class);
        if(Objects.nonNull(patchMapping)){
            methodUrl = patchMapping.value().length > 0 ? patchMapping.value()[0] : "";
        }
        RequestMapping requestMapping = method.getAnnotation(RequestMapping.class);
        if(Objects.nonNull(requestMapping)){
            methodUrl = requestMapping.value().length > 0 ? requestMapping.value()[0] : "";
        }
        return methodUrl;
    }
}
